﻿#include"stdafx.h"
#ifdef LK_REFLECTION_
namespace LK
{
	namespace Reflection
	{
		index_t PLibraryNode::Compare(PLibraryNode const&n1, PLibraryNode const&n2){
			index_t i = PString::Compare(n1.GetName(), n2.GetName());
			return i;
		}
		index_t PLibraryNode::StringCompare(PLibraryNode const&n1, PString const&n2){
			return PString::Compare(n1.GetName(), n2);
		}
		PNamespaceNode& PTypeLibrary::GetGlobleNamespaceRef()const { return Ptr()->GetGlobleNamespaceRef(); }
		PString PTypeLibrary::GetSeparatorRef()const { return Ptr()->Separator; }
		PTypeNode PTypeLibrary::GetTypeNodeByInfo(const PType&t)const
		{
			if (t.IsNull() || !t.IsPureType())return PTypeNode();
			return GetTypeNodeByInfo(t.GetID());
		}
		PTypeNode PTypeLibrary::GetTypeNodeByInfo(index_t id)const
		{
			if (id == 0)return PTypeNode();
			if (id > 0)
			{
				if (Ptr()->GetStaticTypesRef().GetLength()<=id)return PTypeNode();
				return GetPtr()->GetStaticTypesRef()[id];
			}
			std::map<index_t, PTypeNode>::iterator it = Ptr()->DynamicTypes.find(id);
			if (it == GetPtr()->DynamicTypes.end())return PTypeNode();
			return it->second;
		}
		void PTypeLibrary::SetTypeNodeByInfo(const PType&t, PTypeNode const&node)const{Ptr()->SetTypeNodeByInfo(t, node);}
		void TypeLibrary::SetTypeNodeByInfo(const PType&t, PTypeNode const&node)
		{
			if (t.IsNull())throw PInvalidArgumentException(L"指定的Type为空");
			index_t id = t.GetID();
			if (id == 0)throw PInvalidArgumentException(L"指定的Type的ID为0");
			if (id > 0)
			{
				if (GetStaticTypesRef().GetLength() <= id)StaticTypes.Resize(id + 1);
				StaticTypes[id] = node;
			}
			else
			{
				std::map<index_t, PTypeNode>::iterator it = DynamicTypes.find(id);
				if (it == DynamicTypes.end())
				{
					if(!node.IsNull())DynamicTypes.insert(std::pair<index_t, PTypeNode>(id, node));
				}
				else
				{
					if (node.IsNull())DynamicTypes.erase(it);
					else it->second = node;
				}
			}
		}
		PNamespaceNode& TypeLibrary::GetGlobleNamespaceRef()
		{
			if (GlobleNamespace.IsNull())GlobleNamespace = new NamespaceNode(L"Globle", this);
			return GlobleNamespace;
		}
		/**
		@brief 获取静态的类型映射（如果映射为空，则自动生成基本类型映射）*/
		Collection::PArray<PTypeNode>& TypeLibrary::GetStaticTypesRef()
		{
			//自动添加类型节点：void,bool,s8,s16,i32,s32,s64,u8,u16,ui32,u32,u64,float,double,long double,char,wchar_t
			if (StaticTypes.IsNull())
			{
				StaticTypes = Collection::PArray<PTypeNode>(20);
				//在全局命名空间中添加基础类型
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"void", PType::Make<void>());
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"char", PType::Make<char>());
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"int", PType::Make<int>());
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"short", PType::Make<short>());
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"long", PType::Make<long>());
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"long long", PType::Make<long long>());
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"signed char", PType::Make<signed char>());
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"signed short", PType::Make<signed short>());
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"unsigned int", PType::Make<unsigned int>());
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"unsigned long", PType::Make<unsigned long>());
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"unsigned long long", PType::Make<unsigned long long>());
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"unsigned char", PType::Make<unsigned char>());
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"wchar_t", PType::Make<wchar_t>());
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"double", PType::Make<double>());
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"float", PType::Make<float>());
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"long double", PType::Make<long double>());
				GetGlobleNamespaceRef().FindOrAddTypeNode(L"bool", PType::Make<bool>());
			}
			return StaticTypes;
		}
		TypeLibrary::TypeLibrary() :GlobleNamespace(), Separator(L".") { }
		PTypeLibrary GetGlobleLibrary()
		{
			static PTypeLibrary lib;
			if (!lib.IsNull())return lib;
			SpinMutex::GetDefaultRef().Lock();
			if(lib.IsNull())lib = new TypeLibrary();
			SpinMutex::GetDefaultRef().UnLock();
			return lib;
		}
		TypeLibrary::~TypeLibrary()
		{
			if(!GlobleNamespace.IsNull())GlobleNamespace.Clear();
		}
	}
}
#endif
